<?php

namespace App\Api\Services;

use App\Api\Models\LogInStorageModel;
use App\Api\Models\LogOutStorageModel;
use App\Api\Models\LogPackageModel;
use App\Api\Models\OverflowBreakagePackageContentModel;
use App\Api\Models\OverflowBreakagePackageModel;
use App\Api\Models\StorageBatchModel;
use App\Api\Models\StorageManageModel;
use App\Models\CheckModel;
use App\Models\OverflowBreakageChecksModel;
use App\Models\OverflowBreakageDetailModel;
use App\Models\OverflowBreakageModel;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class OverflowBreakageService
{
    static public function add($mainInfo, $data)
    {
        DB::beginTransaction();

        try {
            isset($data['proof_image']) ? $mainInfo['proof_image'] = $data['proof_image'] : '';
            $remark = '';
            //创建主单信息
            $mainId = OverflowBreakageModel::insertGetId($mainInfo);

            //商品详细添加
            $goodsInfo = json_decode($data['goods_info'], true);

            if (!empty($goodsInfo)) {
                foreach ($goodsInfo as &$value) {
                    $value['main_id'] = $mainInfo['main_id'];
                    $value['o_b_main_id'] = $mainId;
                    $value['created_at'] = time();
                    if (isset($value['remark']) && !empty($value['remark'])) {
                        if (!$remark) {
                            $remark = $value['remark'];
                        } else {
                            $remark = $remark . ',' . $value['remark'];
                        }
                    }
                }
                OverflowBreakageDetailModel::insert($goodsInfo);
            }

            if($data['type'] == 1) {
                $packageInfo = json_decode($data['package_info'], true);

                unset($val);
                if (!empty($packageInfo)) {
                    $arr = [];
                    foreach ($packageInfo as $val) {
                        $id = OverflowBreakagePackageModel::insertGetId([
                            'package_id' => $val['package_id'],
                            'num' => $val['num'],
                            'main_id' => $mainInfo['main_id'],
                            'o_b_main_id' => $mainId,
                            'remark' => empty($val['remark']) ? '' : $val['remark'],
                            'created_at' => time(),
                        ]);

                        foreach ($val['package_content'] as $k => $v) {
                            $arr[] = [
                                'package_id' => $val['package_id'],
                                'num' => $v['num'],
                                'total_num' => $val['num'] * $v['num'],
                                'o_b_p_id' => $id,
                                'storage_manage_id' => $v['storage_manage_id'],
                                'type_id' => $v['type_id'],
                                'storage_id' => $v['storage_id'],
                                'o_b_id' => $mainId,
                                'main_id' => $mainInfo['main_id'],
                                'created_at' => time(),
                            ];
                        }
                    }

                    OverflowBreakagePackageContentModel::insert($arr);
                }
            }

            //添加审批人
            $checkInfo = json_decode($data['check_info'], true);
            foreach ($checkInfo as &$val) {
                $val['o_b_main_id'] = $mainId;
                $val['admin_id'] = $val['id'];
                $val['created_at'] = time();
                unset($val['id']);
            }
            OverflowBreakageChecksModel::insert($checkInfo);
            $checkPerson = OverflowBreakageChecksModel::where(['o_b_main_id' => $mainId])->pluck('admin_id')->toArray();
            $checkPerson = implode(',', $checkPerson);

            CheckModel::insert([
                'type' => $data['type'],
                'all_id' => $mainId,
                'main_id' => $mainInfo['main_id'],
                'user_id' => $mainInfo['user_id'],
                'remark' => $remark == '' ? '' : $remark,
                'check_person' => $checkPerson,
                'check_person_tmp' => $checkPerson,
                'created_at' => time(),
                'updated_at' => time()
            ]);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug('新建报损报溢:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //报溢报损列表
    static public function list($data, $userId)
    {
        $condition = [];
        if($data['repeal_status'] != 2) {
            $condition['repeal_status'] = ['EQ' => $data['repeal_status']];
        }

        $condition1 = [];
        if($data['status'] != 3) {
            $condition1['status'] = ['EQ' => $data['status']];
        }

        if ($data['type']) {
            $result = SELF::breakage($data, $userId, $condition, $condition1);
        } else {
            $result = SELF::overflow($data, $userId, $condition, $condition1);
        }

        return $result;
    }

    static public function overflow($data, $userId, $condition, $condition1)
    {
        $keyword = empty($data['keyword']) ?'': $data['keyword'];

        $mainIdCollection = OverflowBreakageDetailModel::getMainId($keyword, $data);

        $mainIdArr = [];
        foreach ($mainIdCollection as $value) {
            $mainIdArr[] = $value['o_b_main_id'];
        }

        return SELF::commonSearch($keyword, $data, $mainIdArr, $userId, $condition, $condition1);
    }

    static private function breakage($data, $userId, $condition, $condition1)
    {
        $keyword = empty($data['keyword']) ?'': $data['keyword'];

        $detailMainIdCollection = OverflowBreakageDetailModel::getMainId($keyword, $data);
        $packageMainIdCollection = OverflowBreakagePackageModel::getMainId($keyword, $data);
        $packageContentMainIdCollection = OverflowBreakagePackageContentModel::getMainId($keyword, $data);

        $mainIdArr = [];

        if(!empty($detailMainIdCollection)) {
            foreach($detailMainIdCollection as $value) {
                $mainIdArr[] = $value['o_b_main_id'];
            }
        }

        if(!empty($packageMainIdCollection)) {
            foreach($packageMainIdCollection as $val) {
                if(!in_array($val['o_b_main_id'], $mainIdArr)) {
                    array_push($mainIdArr, $val['o_b_main_id']);
                }
                else {
                    $mainIdArr[] = $val['o_b_main_id'];
                }
            }
        }

        if(!empty($packageContentMainIdCollection)) {
            foreach($packageContentMainIdCollection as $v) {
                if(!in_array($v['o_b_id'], $mainIdArr)) {
                    array_push($mainIdArr, $v['o_b_id']);
                }
                else {
                    $mainIdArr[] = $v['o_b_id'];
                }
            }
        }

        return SELF::commonSearch($keyword, $data, $mainIdArr, $userId, $condition, $condition1);
    }

    static public function commonSearch($keyword = '', $data, $mainIdArr = [], $userId = [], $condition = [], $condition1 = [])
    {
        $query = OverflowBreakageModel::select(
            'a.*',
            'b.username',
            'b.nickname'
        )
            ->from('overflow_breakage as a')
            ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
            ->with('goodsInfo', function ($query) use ($keyword) {
                $query->select(
                    'overflow_breakage_detail.*',
                    'b.materiel_name',
                    'b.type_name',
                    'b.materiel_no',
                    'c.storage_name',
                    'c.storage_address',
                )
                    ->leftJoin('materiel_type as b', 'b.id', '=', 'overflow_breakage_detail.materiel_type_id')
                    ->leftJoin('storage as c', 'c.id', '=', 'overflow_breakage_detail.warehouse_id');
            })
            ->with('packageInfo', function($query) {
                $query->select(
                    'overflow_breakage_package.*',
                    'a.package_name'
                )
                    ->leftJoin('package as a', 'a.id', '=', 'overflow_breakage_package.package_id')
                    ->with('packageContent', function($query) {
                        $query->select(
                            'overflow_breakage_package_content.*',
                            'a.materiel_name',
                            'a.type_name',
                            'a.materiel_no',
                            'b.storage_name',
                            'b.storage_address',
                        )
                            ->leftJoin('materiel_type as a', 'a.id', '=', 'overflow_breakage_package_content.type_id')
                            ->leftJoin('storage as b', 'b.id', '=', 'overflow_breakage_package_content.storage_id');
                    });
            })
            ->with('checkInfo');
            if(isset($data['type'])) {
                $query->where('type', $data['type']);
            }
            $query->where($condition1)
            ->where($condition)
            ->where($userId);

        if (!empty($data['start_time'])) {
            $startTimeArr = explode(' ', $data['start_time']);
            $startTime = strtotime($startTimeArr[0] . ' 00:00:00');
        }

        if (!empty($data['end_time'])) {
            $endTimeArr = explode(' ', $data['end_time']);
            $endTime = strtotime($endTimeArr[0] . ' 23:59:59');
        }

        if (!empty($startTime) && !empty($endTime)) {
            $query->whereBetween('a.created_at', [$startTime, $endTime]);
        } else if (!empty($startTime) && empty($endTime)) {
            $query->where('a.created_at', '>=', $startTime);
        } else if (empty($startTime) && !empty($endTime)) {
            $query->where('a.created_at', '<=', $endTime);
        }

        if(!isset($data['id'])) {
            $query = $query->whereIn('a.id', $mainIdArr)->orderBy('a.id', 'desc')
                ->paginate($data['pageSize'], ['*'], '', $data['currentPage'])->toArray();
        }
        else {
            $query = $query->where('a.id', $data['id'])->orderBy('a.id', 'desc')->first();
        }

        return $query;
    }

    //报溢报损撤销
    static public function repeal($data)
    {
//        $overflowBreakageInfo = OverflowBreakageModel::where('id', $data['id'])->first();
        $overflowBreakageModel = OverflowBreakageModel::find($data['id']);
//
        if($overflowBreakageModel['repeal_status'] == 1) {
            return ['code' => 1, 'msg' => '不可重复操作', 'data' => ''];
        }

        DB::beginTransaction();

        try {
            //更新审批状态
            if($overflowBreakageModel['type']==0) {//报溢
                CheckModel::where(['main_id'=>$overflowBreakageModel['main_id'],'all_id'=>$data['id'],'type'=>0])->update(['repeal_status'=>1]);//更新报溢审批状态
            }else{
                CheckModel::where(['main_id'=>$overflowBreakageModel['main_id'],'all_id'=>$data['id'],'type'=>1])->update(['repeal_status'=>1]);//更新报损审批状态
            }

            if($overflowBreakageModel['type'] == 0) {//报溢
                SELF::overflowRepeal($data);
            }
            else {//报损
                SELF::breakageRepeal($data);
            }

            $overflowBreakageModel->repeal_status = 1;
            $overflowBreakageModel->save();

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('报溢报损撤销异常：'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    static private function overflowRepeal($data)
    {
        $logInfo = LogInStorageModel::where([
            'all_id_type' => 1,
            'all_id' => $data['id']
        ])->get()->toArray();

           if(!empty($logInfo)) {
               foreach($logInfo as $value) {
                   $storageManageInfo = StorageManageModel::where('id', $value['curr_storage_manage_id'])
                       ->orderBy('in_storage_num', 'DESC')
                       ->first();

                   if($storageManageInfo['in_storage_num'] < $value['operate_num']) {
                       throw new \Exception($storageManageInfo['materiel_name'].'库存不足，无法完成撤销');
                   }

                   if($storageManageInfo['virtual_storage_num'] < $value['operate_num']) {
                       throw new \Exception($storageManageInfo['materiel_name'].'虚拟库存不足，无法完成撤销');
                   }

                   if(!empty($value['batch_id'])) {
                       $batchInfo = StorageBatchModel::where('id', $value['batch_id'])->first();

                       if($value['operate_num'] < $batchInfo['batch_left_num']) {
                           throw new \Exception($storageManageInfo['materiel_name'].'批次数量不足，无法完成出库，无法完成撤销');
                       }

                       StorageBatchModel::where('id', $value['batch_id'])->decrement('batch_left_num', $value['operate_num']);
                   }

                   LogInStorageModel::where([
                       'all_id_type' => 1,
                       'all_id' => $data['id']
                   ])->update(['is_cancel' => 1]);

                   StorageManageModel::where('id', $value['curr_storage_manage_id'])
                       ->update([
                           'in_storage_num' => DB::raw("in_storage_num - ".$value['operate_num']),
                           'virtual_storage_num' => DB::raw("virtual_storage_num - ".$value['operate_num']),
                           'delete_flag' => 0
                       ]);
               }
           }

            return true;
    }

    static private function breakageRepeal($data)
    {
        $logInfo = LogOutStorageModel::where([
            'all_id_type' => 1,
            'all_id' => $data['id'],
            'is_cancel' => 0
        ])->get()->toArray();

        $logPackageInfo = LogPackageModel::with('hasManyContent')
            ->where([
                'all_id_type' => 1,
                'all_id' => $data['id'],
                'is_cancel' => 0
            ])->get()->toArray();

            if(!empty($logInfo)) {
                foreach($logInfo as $value) {
                    LogOutStorageModel::where([
                        'all_id_type' => 1,
                        'all_id' => $data['id']
                    ])->update(['is_cancel' => 1]);

                    $storageManageInfo = StorageManageModel::where('id', $value['curr_storage_manage_id'])
                        ->orderBy('in_storage_num', 'DESC')
                        ->first();

//                    if($storageManageInfo['in_storage_num'] < $value['operate_num']) {
//                        throw new \Exception($storageManageInfo['materiel_name'].'库存不足，无法完成撤销');
//                    }

//                    if($storageManageInfo['virtual_storage_num'] < $value['operate_num']) {
//                        throw new \Exception($storageManageInfo['materiel_name'].'虚拟库存不足，无法完成撤销');
//                    }

                    StorageManageModel::where('id', $value['curr_storage_manage_id'])
                        ->update([
                            'in_storage_num' => DB::raw("in_storage_num + ".$value['operate_num']),
                            'virtual_storage_num' => DB::raw("virtual_storage_num + ".$value['operate_num']),
                            'delete_flag' => 0
                        ]);
                }
            }

            if(!empty($logPackageInfo)) {
                foreach($logPackageInfo as $val) {
                    foreach($val['has_many_content'] as $v) {
                        $storageManageInfo = StorageManageModel::where('id', $v['out_storage_manage_id'])
                            ->orderBy('in_storage_num', 'DESC')
                            ->first();

//                        if($storageManageInfo['in_storage_num'] < $v['operate_num']) {
//                            throw new \Exception($storageManageInfo['materiel_name'].'库存不足，无法完成撤销');
//                        }

                        StorageManageModel::where('id', $v['out_storage_manage_id'])
                            ->update([
                                'in_storage_num' => DB::raw("in_storage_num + ".$v['operate_num']),
                                'virtual_storage_num' => DB::raw("virtual_storage_num + ".$v['operate_num']),
                                'delete_flag' => 0
                            ]);
                    }
                }
            }

            return true;
    }
}
